package org.springframework.boot.netty.argumentResolver;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.netty.NettyProperties;
import org.springframework.boot.netty.exception.ConvertException;
import org.springframework.boot.netty.listener.Message;
import org.springframework.context.ApplicationContext;
import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.DefaultFormattingConversionService;

public abstract class HandlerMethodArgumentResolverAdapter implements HandlerMethodArgumentResolver {

    protected ApplicationContext applicationContext;

    protected NettyProperties nettyProperties;

    protected ConversionService conversionService;


    private final static Logger logger = LoggerFactory.getLogger(HandlerMethodArgumentResolverAdapter.class);


    @Override
    public boolean supportsParameter(Class<?> receiveClass,MethodParameter methodParameter){
        return false;
    }

    @Override
    public abstract Object resolveArgument(Message message, MethodParameter methodParameter) throws ConvertException ;


    public Object resolveAndConvertArgument(Message message, MethodParameter methodParameter){
        Object convertIfNecessary = convertIfNecessary(message, methodParameter);
        if(null==convertIfNecessary){
            convertIfNecessary = resolveArgument(message, methodParameter);
        }
        return convertIfNecessary;
    }

    /**
     * 给conversionService一个机会，优先转换，用户可以自定义各种converter加入conversionService中并优先得到执行
     * @param message
     * @param methodParameter
     * @return
     */
    private Object convertIfNecessary(Message message, MethodParameter methodParameter){
        // 标注有自定义注解，不能使用converter解析
        if(methodParameter.getParameter().getAnnotations().length > 0){
            return null;
        }
        if(this.conversionService.canConvert(message.getContent().getClass(),methodParameter.getParameter().getType())){
            return this.conversionService.convert(message.getContent(), methodParameter.getParameter().getType());
        }else {
            return null;
        }

    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        this.nettyProperties = this.applicationContext.getBean(NettyProperties.class);
        try {
            this.conversionService = this.applicationContext.getBean(ConversionService.class);
        }catch (BeansException e){
            logger.debug("IOC container not found bean of conversionService.class");
        }
        this.conversionService = (conversionService == null) ? new DefaultFormattingConversionService() : conversionService;
    }

}